package com.duowan.cms.common.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;

import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.JsonConfig;
import net.sf.json.processors.DefaultValueProcessor;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.JSONUtils;
import net.sf.json.util.PropertyFilter;

/**
 * 
 * 接口或类的说明
 *
 * <br>==========================
 * <br> 版本：1.0
 * <br>==========================
 */
public abstract class JsonConfigUtil {

    private JsonConfigUtil() {
    }

    /**
     * 方法用途和描述:获得JSON格式化日期的配置yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static JsonConfig getJsonConfig() {
        return getJsonConfigInstans();
    }

    /**
     * 方法用途和描述:获得JSON格式化日期的配置yyyy-MM-dd HH:mm:ss
     * @param filter JSON字段过滤
     * @return
     */
    public static JsonConfig getJsonConfig(PropertyFilter filter) {
        JsonConfig cfg = getJsonConfigInstans();
        cfg.setJsonPropertyFilter(filter);
        return cfg;
    }

    /**
     * 方法用途和描述:获得JSON格式化日期的配置yyyy-MM-dd HH:mm:ss
     * @param filter JSON字段过滤
     * @param jsonValueProcessor JSON字段转换
     * @return
     */
    public static JsonConfig getJsonConfig(PropertyFilter filter, Map<Class<?>, JsonValueProcessor> jsonValueProcessor) {
        JsonConfig cfg = new JsonConfig();
        cfg.setJsonPropertyFilter(APPLY_ALL_PROPERTIES);

        if (jsonValueProcessor != null && !jsonValueProcessor.isEmpty()) {
            for (Map.Entry<Class<?>, JsonValueProcessor> entry : jsonValueProcessor.entrySet())
                cfg.registerJsonValueProcessor(entry.getKey(), entry.getValue());

            if (!jsonValueProcessor.containsKey(java.sql.Timestamp.class))
                cfg.registerJsonValueProcessor(java.sql.Timestamp.class, PROCESSOR_DATE);

            if (!jsonValueProcessor.containsKey(java.sql.Date.class))
                cfg.registerJsonValueProcessor(java.sql.Date.class, PROCESSOR_DATE);

            if (!jsonValueProcessor.containsKey(java.util.Date.class))
                cfg.registerJsonValueProcessor(java.util.Date.class, PROCESSOR_DATE);

            if (!jsonValueProcessor.containsKey(java.math.BigDecimal.class))
                cfg.registerJsonValueProcessor(java.math.BigDecimal.class, PROCESSOR_BIGDECIMAL);
        }

        return cfg;
    }

    /** 允许所有类型转换 **/
    public static final PropertyFilter APPLY_ALL_PROPERTIES;
    /** 只允许一些常用类型转换 **/
    public static final PropertyFilter APPLY_COMMON_PROPERTIES;
    /** BigDecimal的JSON转换 **/
    public static final JsonValueProcessor PROCESSOR_BIGDECIMAL;
    /** 日期类型的JSON转换 **/
    public static final JsonValueProcessor PROCESSOR_DATE;

    static {
        JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] { DateUtil.defaultDateTimePatternStr, DateUtil.defaultDatePatternStr }));

        APPLY_ALL_PROPERTIES = new PropertyFilter() {
            public boolean apply(Object source, String name, Object value) {
                return false;//返回false才被序列化到json
            }
        };
        APPLY_COMMON_PROPERTIES = new PropertyFilter() {
            public boolean apply(Object source, String name, Object value) {
                if (value == null)
                    return true;
                if (value instanceof String || value instanceof Integer || value instanceof Long || value instanceof Boolean || value instanceof Short
                        || value instanceof BigDecimal || value instanceof BigInteger || value instanceof Byte || value instanceof Date || value instanceof Double
                        || value instanceof Float || value instanceof Timestamp || value.getClass().isEnum()) {
                    return false;
                }
                return true;
            }
        };
        PROCESSOR_BIGDECIMAL = new JsonValueProcessor() {
            public Object processArrayValue(Object value, JsonConfig config) {
                String[] obj = {};
                if (value instanceof java.math.BigDecimal[]) {
                    java.math.BigDecimal[] values = (java.math.BigDecimal[]) value;
                    obj = new String[values.length];
                    for (int i = 0; i < values.length; i++) {
                        obj[i] = values[i] == null ? null : values[i].setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                    }
                }
                return obj;
            }

            public Object processObjectValue(String key, Object value, JsonConfig config) {
                if (value == null || !(value instanceof java.math.BigDecimal)) {
                    return null;
                }
                return ((BigDecimal) value).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            }
        };
        PROCESSOR_DATE = new JsonValueProcessor() {
            public Object processArrayValue(Object value, JsonConfig config) {
                return processDateArrayValue(value, config);
            }

            public Object processObjectValue(String key, Object value, JsonConfig config) {
                return processDateObjectValue(key, value, config);
            }
        };
    }

    /**
     * 方法用途和描述:用于处理日期对象数组转换字符串数组
     * @param value 日期对象数据
     * @param config
     * @param dateFormat 日期格式
     * @return
     */
    private static Object processDateArrayValue(Object value, JsonConfig config) {
        String[] obj = {};
        if (value == null)
            return obj;

        if (value instanceof Timestamp[]) {
            Timestamp[] dates = (Timestamp[]) value;
            obj = new String[dates.length];
            for (int i = 0; i < dates.length; i++) {
                obj[i] = DateUtil.convertDate2Str(dates[i]);
            }
        } else if (value instanceof Date[]) {
            Date[] dates = (Date[]) value;
            obj = new String[dates.length];
            for (int i = 0; i < dates.length; i++) {
                obj[i] = DateUtil.convertDate2Str(dates[i]);
            }
        }

        return obj;
    }

    /**
     * 方法用途和描述:用于处理日期对象转换字符串
     * @param key 
     * @param value 日期对象
     * @param config 
     * @param dateFormat 日期格式
     * @return
     */
    private static Object processDateObjectValue(String key, Object value, JsonConfig config) {
        if (value == null)
            return null;

        if (value instanceof Timestamp) {
            String str = DateUtil.convertDate2Str((Timestamp) value);
            return str;
        } else if (value instanceof Date) {
            String str = DateUtil.convertDate2Str((Date) value);
            return str;
        }

        return value.toString();
    }

    /**
    * 方法用途和描述: 获取JsonConfig的实例
    * @return
     */
    protected static JsonConfig getJsonConfigInstans() {
        JsonConfig cfg = new JsonConfig();
        cfg.registerDefaultValueProcessor(Integer.class, new DefaultValueProcessor() {
            public Object getDefaultValue(@SuppressWarnings("rawtypes") Class type) {
                return null;
            }
        });
        cfg.registerJsonValueProcessor(Timestamp.class, PROCESSOR_DATE);
        cfg.registerJsonValueProcessor(java.sql.Date.class, PROCESSOR_DATE);
        cfg.registerJsonValueProcessor(java.util.Date.class, PROCESSOR_DATE);
        cfg.registerJsonValueProcessor(BigDecimal.class, PROCESSOR_BIGDECIMAL);
        return cfg;
    }

    /**
     * 方法用途和描述: 获取JsonConfig的实例
     * @return
      */
    protected static JsonConfig getJsonConfigInstans4CommonProperties() {
        JsonConfig cfg = getJsonConfigInstans();
        cfg.setJsonPropertyFilter(APPLY_COMMON_PROPERTIES);
        return cfg;
    }

    /**
     * 方法用途和描述:获得JSON格式化日期的配置yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static JsonConfig getJsonConfig4CommonProperties() {
        return getJsonConfigInstans4CommonProperties();
    }
}
